package com.opennews.openplatform.familyexpenseapi.config

import com.opennews.openplatform.familyexpenseapi.controller.AuthInterceptor
import org.springframework.context.annotation.Configuration
import org.springframework.core.env.Environment
import org.springframework.web.bind.annotation.RestController
import org.springframework.web.method.HandlerTypePredicate
import org.springframework.web.servlet.config.annotation.InterceptorRegistry
import org.springframework.web.servlet.config.annotation.PathMatchConfigurer
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer

@Configuration
class WebConfig(
    private val appConfigProperties: AppConfigProperties,
    private val authInterceptor: AuthInterceptor,
    private val env: Environment,
) : WebMvcConfigurer {
    companion object {
        const val API_PATH_PREFIX: String = "api"
    }

    override fun configurePathMatch(configurer: PathMatchConfigurer) {
        configurer.addPathPrefix(API_PATH_PREFIX, HandlerTypePredicate.forAnnotation(RestController::class.java))
    }

    override fun addInterceptors(registry: InterceptorRegistry) {
        registry.addInterceptor(authInterceptor)
            .addPathPatterns("/$API_PATH_PREFIX/**")
    }

    /**
     * Serves local content as web server static resource via embedded tomcat.
     */
    /**
     * https://www.baeldung.com/spring-mvc-static-resources
     */
    override fun addResourceHandlers(registry: ResourceHandlerRegistry) {
        // IMPORTANT!!!
        // Never includes leading slash for addResourceLocations. Otherwise you would encounter error: java.net.UnknownHostException.
        // And this error leads to "Resolved [org.springframework.http.converter.HttpMessageNotWritableException:
        // No converter for [class java.util.LinkedHashMap] with preset Content-Type 'image/jpeg;charset=UTF-8']"
        //
        // The correct value is like: file:/opt/files/
        // NOT file://opt/files/
        // NOT file:opt/files/
        val rootFilePath = appConfigProperties.resource.upload.rootFilePath

        // Removes all leading slashes if existed.
        // In Java, String.replaceFirst(String regex, String replacement) interprets the first argument as a regular expression.
        //
        // In Kotlin, there are two different replaceFirst() methods:
        // - fun String.replaceFirst(oldValue: String, newValue: String) → Literal string match (no regex!)
        // - fun String.replaceFirst(regex: Regex, replacement: String) → Regex-aware
        //
        // That's why rootFilePath?.replaceFirst("^/*", "") does NOT work as you expect.
        val resourceLocation = rootFilePath?.replaceFirst(Regex("^/*"), "")

        registry.addResourceHandler("${appConfigProperties.resource.staticResourcesUrl}/**")
            .addResourceLocations("file:/$resourceLocation")
    }
}